#include "linux/types.h"
#include "linux/smp.h"
#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/of.h"
#include "linux/of_fdt.h"
#include "linux/printk.h"
#include "linux/memblock.h"
#include "linux/cache.h"
#include "linux/threads.h"
#include "asm/mach/arch.h"
#include "asm/ptrace.h"

void imx6u_clkinit(void);
void clk_enable(void);
void led_init(void);
void BOARD_InitMemory(void);
void paging_init(void);
int imx6ul_uart_init(void);
void arm_memblock_init(const struct machine_desc *mdesc);


extern struct machine_desc *setup_machine_fdt(void *dt_phys);

struct stack 
{
	u32 irq[32];
	u32 abt[32];
	u32 und[32];
	u32 fiq[32];
} ____cacheline_aligned;


unsigned int __machine_arch_type;
unsigned int processor_id;
struct machine_desc *machine_desc;
unsigned int __atags_pointer __initdata;

static struct stack stacks[NR_CPUS];

static int  customize_machine(void)
{
    machine_desc->init_machine();
	return 0;
}

void early_setup_arch(void)
{
 	int ret;
	
	imx6u_clkinit();			/* 初始化系统时钟 			*/
	clk_enable();				/* 使能所有的时钟 			*/
	
	BOARD_InitMemory();
    
	ret = imx6ul_uart_init();
    if (ret < 0)
    {

    }
	
}

void cpu_init(void)
{
    unsigned int cpu = smp_processor_id();
	struct stack *stk = &stacks[cpu];

    __asm__ (
	"msr	cpsr_c, %1\n\t"  // 切换到IRQ模式，并禁用中断(设置F和I位), %1 表示第一个输入操作数，包含模式位和中断标志
	"add	r14, %0, %2\n\t" // 计算IRQ模式堆栈地址: stk + offsetof(struct stack, irq[0])
	"mov	sp, r14\n\t"     // 设置IRQ模式的堆栈指针

	"msr	cpsr_c, %3\n\t"
	"add	r14, %0, %4\n\t"
	"mov	sp, r14\n\t"

	"msr	cpsr_c, %5\n\t"
	"add	r14, %0, %6\n\t"
	"mov	sp, r14\n\t"

	"msr	cpsr_c, %7\n\t"
	"add	r14, %0, %8\n\t"
	"mov	sp, r14\n\t"

	"msr	cpsr_c, %9"
	    :
	    : "r" (stk), // %0 - 堆栈基地址, "r" (stk)：将stk变量放入通用寄存器作为基地址
	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), //"I"：表示立即数约束，要求编译器使用常量表达式
	      "I" (offsetof(struct stack, irq[0])),
	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
	      "I" (offsetof(struct stack, abt[0])),
	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
	      "I" (offsetof(struct stack, und[0])),
	      "I" (PSR_F_BIT | PSR_I_BIT | FIQ_MODE),
	      "I" (offsetof(struct stack, fiq[0])),
	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
	    : "r14"); //告知编译器r14(LR)寄存器在此汇编代码中被使用，编译器会在进入汇编前保存其值
}

static void setup_processor(void)
{
	cpu_init();
}

void setup_arch(void *fdt)
{
    struct machine_desc *mdesc;

    setup_processor();
    
    memblock_init();

    early_setup_arch();

    mdesc = setup_machine_fdt(fdt);

    arm_memblock_init(mdesc);

    unflatten_device_tree();

    machine_desc  = mdesc;

    of_dump_device_tree();

	paging_init();   
}

arch_initcall(customize_machine);
